﻿using System;
using System.Runtime.InteropServices;
using Xtensive.IoC;
using Xtensive.Orm;
using Xtensive.Orm.Model;
using Xtensive.Tuples;
using Tuple = Xtensive.Tuples.Tuple;

namespace CustomKeyGenerator.Services
{
    [Service(typeof (KeyGenerator), Name = "SequentialGuidGenerator")]
    public class SequentialGuidGenerator : KeyGenerator
    {
        public override void Initialize(Domain ownerDomain, TupleDescriptor keyTupleDescriptor)
        {
            // Nothing to be done here
        }

        public override Tuple GenerateKey(KeyInfo keyInfo, Session session)
        {
            // Creating tuple for key
            var result = Tuple.Create(keyInfo.TupleDescriptor);

            // Setting the first column of tuple with generated guid value
            result.SetValue(0, GenerateGuid());
            return result;
        }

        /*
         * See http://stackoverflow.com/a/170363/138573 for details
         */
        [DllImport("rpcrt4.dll", SetLastError = true)]
        static extern int UuidCreateSequential(out Guid guid);

        private static Guid GenerateGuid()
        {
            const int RPC_S_OK = 0;
            Guid g;
            return UuidCreateSequential(out g) != RPC_S_OK ? System.Guid.NewGuid() : g;
        }
    }
}